package com.wxd.woff.table.glyf;

import java.io.IOException;

import com.wxd.woff.AbstractOTFDataStream;

/**
 * @Description: 功能描述：TODO
 *
 * @ClassName: GlyfCompositeComp
 * @author: Wang Xindong
 * @date: 2018年9月5日 下午3:08:05
 * @email: wangxindong@travelsky.com
 * @Copyright: Copyright (c) 2018. All rights reserved.
 */
public class GlyfCompositeComp {

	/**
	 * If set, the arguments are words; otherwise, they are bytes.
	 */
	protected static final short ARG_1_AND_2_ARE_WORDS = 0x0001;
	/**
	 * If set, the arguments are xy values; otherwise they are points.
	 */
	protected static final short ARGS_ARE_XY_VALUES = 0x0002;
	/**
	 * If set, xy values are rounded to those of the closest grid lines.
	 */
	protected static final short ROUND_XY_TO_GRID = 0x0004;
	/**
	 * If set, there is a simple scale; otherwise, scale = 1.0.
	 */
	protected static final short WE_HAVE_A_SCALE = 0x0008;
	/**
	 * Indicates at least one more glyph after this one.
	 */
	protected static final short MORE_COMPONENTS = 0x0020;
	/**
	 * The x direction will use a different scale from the y direction.
	 */
	protected static final short WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
	/**
	 * There is a 2 by2 transformation that will be used to scale the component.
	 */
	protected static final short WE_HAVE_A_TWO_BY_TWO = 0x0080;
	/**
	 * Following the last component are instructions for the composite character.
	 */
	protected static final short WE_HAVE_INSTRUCTIONS = 0x0100;
	/**
	 * If set, this forces the aw and lsb (and rsb) for the composite to be equal to
	 * those from this original glyph.
	 */
	protected static final short USE_MY_METRICS = 0x0200;
	private final int flags;
	private final int glyphIndex;
	private final int argument1;
	private final int argument2;

	private int firstIndex;
	private int firstContour;
	private double xscale = 1.0;
	private double yscale = 1.0;
	private double scale01 = 0.0;
	private double scale10 = 0.0;
	private int xtranslate = 0;
	private int ytranslate = 0;
	private int point1 = 0;
	private int point2 = 0;

	public GlyfCompositeComp(AbstractOTFDataStream stream) throws IOException {
		flags = stream.readSignedShort();
		glyphIndex = stream.readUnsignedShort();
		if ((flags & ARG_1_AND_2_ARE_WORDS) != 0) {
			argument1 = stream.readSignedShort();
			argument2 = stream.readSignedShort();
		} else {
			argument1 = stream.readSignedByte();
			argument2 = stream.readSignedByte();
		}

		// Assign the arguments according to the flags
		if ((flags & ARGS_ARE_XY_VALUES) != 0) {
			xtranslate = argument1;
			ytranslate = argument2;
		} else {
			point1 = argument1;
			point2 = argument2;
		}

		// Get the scale values (if any)
		if ((flags & WE_HAVE_A_SCALE) != 0) {
			int i = stream.readSignedShort();
			xscale = yscale = i / (double) 0x4000;
		} else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0) {
			short i = stream.readSignedShort();
			xscale = i / (double) 0x4000;
			i = stream.readSignedShort();
			yscale = i / (double) 0x4000;
		} else if ((flags & WE_HAVE_A_TWO_BY_TWO) != 0) {
			int i = stream.readSignedShort();
			xscale = i / (double) 0x4000;
			i = stream.readSignedShort();
			scale01 = i / (double) 0x4000;
			i = stream.readSignedShort();
			scale10 = i / (double) 0x4000;
			i = stream.readSignedShort();
			yscale = i / (double) 0x4000;
		}
	}

	public int scaleX(int x, int y) {
		return Math.round((float) (x * xscale + y * scale10));
	}

	public int scaleY(int x, int y) {
		return Math.round((float) (x * scale01 + y * yscale));
	}

	public int getFirstIndex() {
		return firstIndex;
	}

	public void setFirstIndex(int firstIndex) {
		this.firstIndex = firstIndex;
	}

	public int getFirstContour() {
		return firstContour;
	}

	public void setFirstContour(int firstContour) {
		this.firstContour = firstContour;
	}

	public double getXscale() {
		return xscale;
	}

	public void setXscale(double xscale) {
		this.xscale = xscale;
	}

	public double getYscale() {
		return yscale;
	}

	public void setYscale(double yscale) {
		this.yscale = yscale;
	}

	public double getScale01() {
		return scale01;
	}

	public void setScale01(double scale01) {
		this.scale01 = scale01;
	}

	public double getScale10() {
		return scale10;
	}

	public void setScale10(double scale10) {
		this.scale10 = scale10;
	}

	public int getXtranslate() {
		return xtranslate;
	}

	public void setXtranslate(int xtranslate) {
		this.xtranslate = xtranslate;
	}

	public int getYtranslate() {
		return ytranslate;
	}

	public void setYtranslate(int ytranslate) {
		this.ytranslate = ytranslate;
	}

	public int getPoint1() {
		return point1;
	}

	public void setPoint1(int point1) {
		this.point1 = point1;
	}

	public int getPoint2() {
		return point2;
	}

	public void setPoint2(int point2) {
		this.point2 = point2;
	}

	public int getFlags() {
		return flags;
	}

	public int getGlyphIndex() {
		return glyphIndex;
	}

	public int getArgument1() {
		return argument1;
	}

	public int getArgument2() {
		return argument2;
	}

}
